home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
general
/
viewers
/
prev
/
prev.lha
/
csg.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-03-11
|
6KB
|
278 lines
#include <math.h>
#include <stdio.h>
#include "art.h"
#include "objs.h"
#include "macro.h"
#include "gram.h"
extern hlist *fhlist;
extern hlist *(*intersects[])();
extern attr *astackp;
extern mats *mstackp;
extern object *objectinit();
/*
* getcsgobj
*
* instantiate an object, mark it as being in csg and return it
*/
object *
getcsgobj(sym, d)
symbol *sym;
details *d;
{
object *obj;
obj = objectinit(sym, d);
return(obj);
}
/*
* makecsgtree
*
* set up a csg object from its tree and details list.
*/
object *
makecsgtree(tree)
csgnode *tree;
{
register object *o;
register csg *c;
switch (tree->type) {
case CSG_SUB:
o = (object *)smalloc(sizeof(object));
c = o->obj.csgt = (csg *)smalloc(sizeof(csg));
o->type = CSG_SUB;
c->leftb = FALSE;
c->rightb = TRUE;
c->left = makecsgtree(tree->u.branch.left);
c->right = makecsgtree(tree->u.branch.right);
c->left->incsg = ADDED;
c->right->incsg = SUBTRACTED;
/* take bounding box of left */
o->bb = c->left->bb;
break;
case CSG_ADD:
o = (object *)smalloc(sizeof(object));
c = o->obj.csgt = (csg *)smalloc(sizeof(csg));
o->type = CSG_ADD;
c->leftb = TRUE;
c->rightb = TRUE;
c->left = makecsgtree(tree->u.branch.left);
c->right = makecsgtree(tree->u.branch.right);
c->left->incsg = ADDED;
c->right->incsg = ADDED;
if (c->left->bb.max[X] > c->right->bb.max[X])
o->bb.max[X] = c->left->bb.max[X];
else
o->bb.max[X] = c->right->bb.max[X];
if (c->left->bb.max[Y] > c->right->bb.max[Y])
o->bb.max[Y] = c->left->bb.max[Y];
else
o->bb.max[Y] = c->right->bb.max[Y];
if (c->left->bb.max[Z] > c->right->bb.max[Z])
o->bb.max[Z] = c->left->bb.max[Z];
else
o->bb.max[Z] = c->right->bb.max[Z];
if (c->left->bb.min[X] < c->right->bb.min[X])
o->bb.min[X] = c->left->bb.min[X];
else
o->bb.min[X] = c->right->bb.min[X];
if (c->left->bb.min[Y] < c->right->bb.min[Y])
o->bb.min[Y] = c->left->bb.min[Y];
else
o->bb.min[Y] = c->right->bb.min[Y];
if (c->left->bb.min[Z] < c->right->bb.min[Z])
o->bb.min[Z] = c->left->bb.min[Z];
else
o->bb.min[Z] = c->right->bb.min[Z];
break;
case CSG_INT:
o = (object *)smalloc(sizeof(object));
c = o->obj.csgt = (csg *)smalloc(sizeof(csg));
o->type = CSG_INT;
c->leftb = FALSE;
c->rightb = FALSE;
c->left = makecsgtree(tree->u.branch.left);
c->right = makecsgtree(tree->u.branch.right);
c->left->incsg = ADDED;
c->right->incsg = ADDED;
/* take overlap */
if (c->left->bb.max[X] < c->right->bb.max[X])
o->bb.max[X] = c->left->bb.max[X];
else
o->bb.max[X] = c->right->bb.max[X];
if (c->left->bb.max[Y] < c->right->bb.max[Y])
o->bb.max[Y] = c->left->bb.max[Y];
else
o->bb.max[Y] = c->right->bb.max[Y];
if (c->left->bb.max[Z] < c->right->bb.max[Z])
o->bb.max[Z] = c->left->bb.max[Z];
else
o->bb.max[Z] = c->right->bb.max[Z];
if (c->left->bb.min[X] > c->right->bb.min[X])
o->bb.min[X] = c->left->bb.min[X];
else
o->bb.min[X] = c->right->bb.min[X];
if (c->left->bb.min[Y] > c->right->bb.min[Y])
o->bb.min[Y] = c->left->bb.min[Y];
else
o->bb.min[Y] = c->right->bb.min[Y];
if (c->left->bb.min[Z] > c->right->bb.min[Z])
o->bb.min[Z] = c->left->bb.min[Z];
else
o->bb.min[Z] = c->right->bb.min[Z];
break;
case OBJECT:
o = getcsgobj(tree->u.sym, (details *)NULL);
break;
default:
fatal("art: illegal type in csgtree.\n");
}
o->nxt = (object *)NULL;
return(o);
}
/*
* csginit
*
* initialise a csg object
*
*/
object *
csginit(sym, d)
symbol *sym;
details *d;
{
details *dl, *nxtdl, *argdt, *otherdt, *nd;
object *o;
surface s;
int sset;
astackp++;
*astackp = *(astackp - 1);
mstackp++;
*mstackp = *(mstackp - 1);
mident4(mstackp->vm);
s = *astackp->s;
/* reverse list */
argdt = (details *)NULL;
for (dl = d; dl != (details *)NULL; dl = nxtdl) {
nxtdl = dl->nxt;
dl->nxt = argdt;
argdt = dl;
}
/* copy sym list */
otherdt = (details *)NULL;
for (dl = sym->u.det->u.csgobj.det; dl != (details *)NULL; dl = dl->nxt) {
nd = (details *)smalloc(sizeof(details));
*nd = *dl;
nd->nxt = otherdt;
otherdt = nd;
}
if (argdt == (details *)NULL) {
argdt = otherdt;
otherdt = (details *)NULL;
}
sset = FALSE;
for (dl = argdt; dl != (details *)NULL; dl = nxtdl) {
switch (dl->type) {
case COLOUR:
s.c.r = dl->u.c.r;
s.c.g = dl->u.c.g;
s.c.b = dl->u.c.b;
sset = TRUE;
break;
case AMBIENT:
s.a.r = dl->u.c.r;
s.a.g = dl->u.c.g;
s.a.b = dl->u.c.b;
sset = TRUE;
break;
case TEXTURE:
dl->u.txt->nxt = astackp->txtlist;
astackp->txtlist = dl->u.txt;
break;
case MATERIAL:
s.ri = dl->u.mat.ri;
s.kd = dl->u.mat.kd;
s.ks = dl->u.mat.ks;
s.ksexp = dl->u.mat.ksexp;
sset = TRUE;
break;
case REFLECTANCE:
s.refl = dl->u.f;
sset = TRUE;
break;
case TRANSPARENCY:
s.trans = dl->u.f;
sset = TRUE;
break;
case ABSORPTION:
s.falloff = dl->u.f;
sset = TRUE;
break;
case ART_TRANSLATE:
art_translate(dl->u.v.x, dl->u.v.y, dl->u.v.z);
break;
case ART_SCALE:
art_scale(dl->u.v.x, dl->u.v.y, dl->u.v.z);
break;
case ART_ROTATE:
art_rotate(dl->u.rot.ang, dl->u.rot.axis);
break;
case ON:
astackp->options |= dl->u.i;
break;
case OFF:
astackp->options &= ~dl->u.i;
break;
case CSG_OBJ:
case OBJECT:
break;
default:
warning("art: bad detail in csg ignored.\n");
}
nxtdl = dl->nxt;
if (nxtdl == (details *)NULL) {
nxtdl = otherdt;
otherdt = (details *)NULL;
}
free(dl);
}
if (sset) {
astackp->s = (surface *)smalloc(sizeof(surface));
*astackp->s = s;
}
o = makecsgtree(sym->u.det->u.csgobj.tree);
astackp--;
mstackp--;
return(o);
}